home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / pmode / pmode386 / pmode.asm < prev    next >
Encoding:
Assembly Source File  |  1993-05-29  |  62.4 KB  |  1,949 lines

  1. ; PMODE v1.29a raw, DPMI, VCPI, & XMS compliant protected mode header.
  2. ; By Tran (a.k.a. Thomas Pytel) of Renaissance.
  3.  
  4.         .386p
  5.  
  6. LOWMIN          = 0             ; minimum free low memory (in K)
  7. EXTMIN          = 0             ; minimum free extended memory (in K)
  8. STAKLEN         = 100h          ; stack size in para (keep below or = 1000h)
  9. STAKSAFE        = 20h           ; safe stack space in para
  10.  
  11. code16  segment para public use16
  12. code16  ends
  13. code32  segment para public use32
  14. code32  ends
  15. codeend segment para stack use32 'stack'
  16. codeend ends
  17.  
  18. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  19. ; Real mode and 16bit code
  20. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  21. code16  segment para public use16
  22.         assume cs:code16, ds:code16
  23.         org 0
  24.  
  25. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  26. ; 16 bit common system data
  27. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  28. errmsg0         db      '386 or better not detected!!!',7,'$'
  29. errmsg1         db      'Not enough low memory!!!',7,'$'
  30. errmsg2         db      'This system is already in V86 mode!!!',7,'$'
  31. errmsg3         db      'Not enough extended memory!!!',7,'$'
  32. errmsg4         db      'Couldn''t enable A20 gate!!!',7,'$'
  33. errmsg5         db      'Extended memory allocation failure. (weird eh???)',7,'$'
  34.  
  35. nullint         db      0cfh            ; IRET instruction
  36. exitrout        dw      exit            ; exit routine, modified if XMS, VCPI
  37.  
  38. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  39. ; 16 bit common system code
  40. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  41. ;═════════════════════════════════════════════════════════════════════════════
  42. intreal:                                ; temporary int to real mode
  43.         pushf
  44. ;-----------------------------------------------------------------------------
  45. callreal:                               ; temporary far call to real mode
  46.         push cs
  47.         push offset icreald
  48.         mov fs,cs:v86r_fs
  49.         mov gs,cs:v86r_gs
  50.         mov eax,cs:v86r_eax
  51.         mov ecx,cs:v86r_ecx
  52.         mov edx,cs:v86r_edx
  53.         mov ebx,cs:v86r_ebx
  54.         mov esi,cs:v86r_esi
  55.         mov edi,cs:v86r_edi
  56.         mov ebp,cs:v86r_ebp
  57.         push cs:tempaddx
  58. icrealif        db      ?       ; CLI or STI
  59.         retf
  60. icreald:
  61.         cli
  62.         pushf
  63.         pop cs:v86r_flags
  64.         mov cs:v86r_eax,eax
  65.         mov cs:v86r_ecx,ecx
  66.         mov cs:v86r_edx,edx
  67.         mov cs:v86r_ebx,ebx
  68.         mov cs:v86r_esi,esi
  69.         mov cs:v86r_edi,edi
  70.         mov cs:v86r_ebp,ebp
  71.         mov cs:v86r_ds,ds
  72.         mov cs:v86r_es,es
  73.         mov cs:v86r_fs,fs
  74.         mov cs:v86r_gs,gs
  75. icrealret       label word              ; return to pmode method, modifiable
  76.         jmp short d_icrealret
  77. ;-----------------------------------------------------------------------------
  78. v_icrealret:                            ; VCPI return to pmode
  79.         mov eax,offset cp_int3_d        ; jump to end of pmode INT32/33
  80.         jmp v_switchtopmode
  81. ;-----------------------------------------------------------------------------
  82. d_icrealret:                            ; DPMI return to pmode
  83.         mov ebx,cs:dp_savedstakoff
  84.         mov dx,cs:dp_savedstaksel
  85.         mov cx,dx
  86.         mov ax,cs:_seldata
  87.         mov si,cs:_selcode
  88.         mov edi,offset dp_int3_d
  89.         jmp cs:d_switchaddx
  90. ;─────────────────────────────────────────────────────────────────────────────
  91. chek_VCPI:                              ; Chek for VCPI
  92.         mov dx,offset v_emmname
  93.         mov ax,3d00h
  94.         int 21h
  95.         jc short chekVCPIa
  96.         mov bx,ax
  97.         mov ax,4400h
  98.         int 21h
  99.         jc short chekVCPIa
  100.         test dh,80h
  101.         jz short chekVCPIa
  102.         mov ax,4407h
  103.         int 21h
  104.         mov dl,al
  105.         mov ah,3Eh
  106.         int 21h
  107.         cmp dl,0FFh
  108.         jne short chekVCPIa
  109.         mov bx,1
  110.         mov ah,43h
  111.         int 67h
  112.         or ah,ah
  113.         jnz short chekVCPIa
  114.         mov v_emshandle,dx
  115.         mov ax,0de00h
  116.         int 67h
  117.         or ah,ah
  118.         clc
  119.         jz short chekVCPId
  120.         mov ah,45h
  121.         int 67h
  122. chekVCPIa:
  123.         stc
  124. chekVCPId:
  125.         ret
  126. ;─────────────────────────────────────────────────────────────────────────────
  127. chek_processor:                         ; Detect if current processor 386
  128.         pushf
  129.         xor ah,ah
  130.         push ax
  131.         popf
  132.         pushf
  133.         pop ax
  134.         and ah,0f0h
  135.         cmp ah,0f0h
  136.         je short detectno386
  137.         mov ah,0f0h
  138.         push ax
  139.         popf
  140.         pushf
  141.         pop ax
  142.         and ah,0f0h
  143.         jz short detectno386
  144.         popf
  145.         ret
  146. detectno386:
  147.         mov dx,offset errmsg0
  148.         jmp short exit16err
  149. ;─────────────────────────────────────────────────────────────────────────────
  150. chek_V86:                               ; Chek if already in V86 mode
  151.         smsw ax
  152.         test al,1
  153.         mov dx,offset errmsg2
  154.         jnz short exit16err
  155.         ret
  156. ;─────────────────────────────────────────────────────────────────────────────
  157. pregetlomem:                            ; Get low memory or abort
  158.         add eax,ds:_lomembase
  159.         mov ebx,ds:_lomemtop
  160.         cmp eax,ebx
  161.         ja short pregetlomema
  162.         mov ecx,eax
  163.         xchg eax,ds:_lomembase
  164.         sub ebx,ecx
  165.         cmp ebx,LOWMIN*1024
  166.         jb short pregetlomema
  167.         ret
  168. pregetlomema:
  169.         mov dx,offset errmsg1
  170. ;─────────────────────────────────────────────────────────────────────────────
  171. exit16err:                              ; Exit program with message
  172.         mov ah,9
  173.         int 21h
  174.         jmp exitrout
  175. ;-----------------------------------------------------------------------------
  176. exit:                                   ; Guess what???
  177.         mov ah,4ch
  178.         int 21h
  179. ;═════════════════════════════════════════════════════════════════════════════
  180. start16:                                ; Program begins here
  181.         cli
  182.         cld
  183.         push cs
  184.         pop ds
  185.  
  186.         call chek_processor             ; is it at least a 386¿
  187.  
  188.         mov ax,es                       ; set up a bunch of pointers
  189.         movzx eax,ax
  190.         shl eax,4
  191.         mov ds:_pspa,eax
  192.         mov eax,code16
  193.         shl eax,4
  194.         mov ds:_code16a,eax
  195.         or dword ptr ds:gdt32code16[2],eax
  196.         or dword ptr ds:gdt32data16[2],eax
  197.         mov ebx,code32
  198.         shl ebx,4
  199.         mov ds:_code32a,ebx
  200.         or dword ptr ds:gdt32code32[2],ebx
  201.         or dword ptr ds:gdt32data32[2],ebx
  202.         add dword ptr ds:c_gdt32addx[2],ebx
  203.         mov eax,codeend
  204.         shl eax,4
  205.         sub eax,ebx
  206.         mov ds:_lomembase,eax
  207.         mov ds:realstackbase,eax
  208.         movzx eax,word ptr es:[2]
  209.         shl eax,4
  210.         sub eax,ebx
  211.         mov ds:_lomemtop,eax
  212.  
  213.         mov eax,STAKLEN*16              ; get stack memory
  214.         call pregetlomem
  215.  
  216.         push es                         ; save PSP seg (DPMI chek kills ES)
  217.         pop fs
  218.  
  219.         mov ax,1687h                    ; chek for DPMI
  220.         int 2fh
  221.         or ax,ax
  222.         jz d_start
  223.  
  224.         call chek_VCPI                  ; chek for VCPI
  225.         jnc v_start
  226.  
  227.         call chek_V86                   ; chek for V86 mode
  228.  
  229.         mov ax,4300h                    ; chek for XMS
  230.         int 2fh
  231.         cmp al,80h
  232.         je x_start
  233.  
  234.         jmp c_start                     ; custom system start
  235. ;─────────────────────────────────────────────────────────────────────────────
  236. ; BL=low vektor base, BH=high vektor base
  237. set8259vektorz:                         ; set new IRQ vektor numbers
  238.         in al,0a1h
  239.         mov ch,al
  240.         in al,21h
  241.         mov cl,al
  242.         mov al,11h
  243.         out 20h,al
  244.         out 0a0h,al
  245.         jmp short $+2
  246.         jmp short $+2
  247.         jmp short $+2
  248.         mov al,bl
  249.         out 21h,al
  250.         mov al,bh
  251.         out 0a1h,al
  252.         jmp short $+2
  253.         jmp short $+2
  254.         jmp short $+2
  255.         mov al,4
  256.         out 21h,al
  257.         mov al,2
  258.         out 0a1h,al
  259.         jmp short $+2
  260.         jmp short $+2
  261.         jmp short $+2
  262.         mov al,1
  263.         out 21h,al
  264.         out 0a1h,al
  265.         mov al,cl
  266.         out 21h,al
  267.         mov al,ch
  268.         out 0a1h,al
  269.         ret
  270. ;─────────────────────────────────────────────────────────────────────────────
  271. enableA20:                              ; hardware enable gate A20
  272.         xor ax,ax
  273.         mov fs,ax
  274.         dec ax
  275.         mov gs,ax
  276.         call testA20
  277.         je short enableA20done
  278.         in al,92h                       ; PS/2 A20 enable
  279.         or al,2
  280.         jmp short $+2
  281.         jmp short $+2
  282.         jmp short $+2
  283.         out 92h,al
  284.         call testA20
  285.         je short enableA20done
  286.         call enableA20o1                ; AT A20 enable
  287.         jnz short enableA20wait
  288.         mov al,0d1h
  289.         out 64h,al
  290.         call enableA20o1
  291.         jnz short enableA20wait
  292.         mov al,0dfh
  293.         out 60h,al
  294.         push offset enableA20wait
  295. enableA20o1:
  296.         mov ecx,20000h
  297. enableA20o1l:
  298.         jmp short $+2
  299.         jmp short $+2
  300.         jmp short $+2
  301.         in al,64h
  302.         test al,2
  303.         loopnz enableA20o1l
  304. enableA20done:
  305.         ret
  306. ;-----------------------------------------------------------------------------
  307. enableA20wait:                          ; wait for A20
  308.         mov cx,800h
  309. enableA20waitl0:
  310.         call testA20
  311.         je enableA20done
  312.         in al,40h
  313.         in al,40h
  314.         mov ah,al
  315. enableA20waitl1:
  316.         in al,40h
  317.         in al,40h
  318.         cmp al,ah
  319.         je enableA20waitl1
  320.         loop enableA20waitl0
  321.         mov dx,offset errmsg4
  322.         jmp exit16err
  323. ;-----------------------------------------------------------------------------
  324. testA20:                                ; Test for enabled A20
  325.         mov al,fs:[0]
  326.         mov ah,al
  327.         not al
  328.         mov gs:[10h],al
  329.         cmp ah,fs:[0]
  330.         mov fs:[0],ah
  331.         ret
  332. ;─────────────────────────────────────────────────────────────────────────────
  333. ; BL=low PIC val, BH=high PIC val, DI->int slot table
  334. setintslots:                            ; set int nums in table to PIC vals
  335.         mov cl,8
  336. setintslotsl0:
  337.         mov [di],bl
  338.         inc di
  339.         inc bl
  340.         dec cl
  341.         jnz setintslotsl0
  342.         mov cl,8
  343. setintslotsl1:
  344.         mov [di],bh
  345.         inc di
  346.         inc bh
  347.         dec cl
  348.         jnz setintslotsl1
  349.         ret
  350. ;─────────────────────────────────────────────────────────────────────────────
  351. ; DI=return to addx
  352. setpmoderegs:                           ; set pmode reg values
  353.         mov ax,28h
  354.         mov ds,ax
  355.         mov al,18h
  356.         mov gs,ax
  357.         mov al,10h
  358.         mov es,ax
  359.         mov fs,ax
  360.         mov ss,ax
  361.         mov esp,STAKLEN*16
  362.         add esp,ds:realstackbase
  363.         jmp di
  364.  
  365. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  366. ; 16 bit DPMI system data
  367. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  368. d_errmsg0       db      'DPMI host is not 32bit!!!',7,'$'
  369. d_errmsg1       db      'Ran out of DPMI descriptors!!!',7,'$'
  370. d_errmsg2       db      'Couldn''t modify DPMI descriptors as needed!!!',7,'$'
  371.  
  372. d_enterpmode    dw      ?,?             ; DPMI switch to pmode addx
  373. d_pspsel        dw      ?               ; stupid PSP selector
  374. d_oldenvsegsel  dw      ?               ; stupid selector we dont want
  375.  
  376. d_oint32vect    dd      ?               ; old int 32h vektor
  377.  
  378. d_switchaddx    dd      ?               ; switch to pmode addx
  379. d_saveaddx      dd      ?               ; save/restore state addx
  380. d_savedstakoff  dw      ?               ; current saved stack offset
  381. d_savedstakseg  dw      ?               ; current saved stack segment
  382.  
  383. d_nintoff       dw      dp_irq0,dp_irq1,dp_irq2,dp_irq3,dp_irq4,dp_irq5,dp_irq6,dp_irq7
  384.                 dw      dp_irq8,dp_irq9,dp_irqa,dp_irqb,dp_irqc,dp_irqd,dp_irqe,dp_irqf
  385.                 dw      dp_int33,dp_int32
  386.  
  387. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  388. ; 16 bit DPMI system code
  389. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  390. ;═════════════════════════════════════════════════════════════════════════════
  391. d_int32:                                ; DPMI/VCPI real INT32: EDX=off
  392.         pushad
  393.         push ds es fs gs
  394.         cli
  395.         mov ax,cs
  396.         mov ds,ax
  397.         mov ds:tempaddx,edx
  398.         mov al,[esp+44]
  399.         shr al,1
  400.         and al,1
  401.         add al,0fah
  402.         mov ds:dp_callpmodeif,al
  403.         push d_savedstakoff
  404.         push d_savedstakseg
  405.         movzx ebx,ds:nextmodestack
  406.         lea eax,[ebx-STAKSAFE*16]
  407.         mov ds:nextmodestack,ax
  408.         add ebx,ds:realstackbase
  409.         sub sp,ds:dp_savelen
  410.         mov d_savedstakoff,sp
  411.         mov d_savedstakseg,ss
  412. d_int32m0:                              ; modified under VCPI
  413. VCPIINT32M0=(v_int32-3)-$               ;
  414.         mov ax,ss
  415.         mov es,ax
  416.         mov di,sp
  417.         xor al,al
  418.         call d_saveaddx
  419.         mov ax,ds:_seldata
  420.         mov cx,ax
  421.         mov dx,ax
  422.         mov si,ds:_selcode
  423.         mov edi,offset dp_callpmode
  424.         jmp d_switchaddx
  425. d_int32d:
  426.         mov di,sp
  427.         mov al,1
  428.         call d_saveaddx
  429.         add sp,ds:dp_savelen
  430. ;-----------------------------------------------------------------------------
  431. d_int32d2:                              ; done from DPMI or VCPI
  432.         pop d_savedstakseg
  433.         pop d_savedstakoff
  434.         add ds:nextmodestack,STAKSAFE*16
  435.         mov bx,ds:v86r_flags
  436.         mov ax,[esp+44]
  437.         and ax,not 8d5h
  438.         and bx,8d5h
  439.         or ax,bx
  440.         mov [esp+44],ax
  441.         pop gs fs es ds
  442.         popad
  443.         iret
  444. ;═════════════════════════════════════════════════════════════════════════════
  445. d_retreal:                              ; Return to real mode
  446.         mov eax,d_oint32vect            ; restore real mode INT32
  447.         mov gs:[32h*4],eax
  448.         mov ax,205h                     ; restore all int vektorz needed
  449.         mov edi,17
  450. d_retreall0:
  451.         mov bl,ds:intslotnum[di]
  452.         lea ebp,[edi*2+edi]
  453.         mov edx,dword ptr ds:dp_ointbuf[ebp*2]
  454.         mov cx,word ptr ds:dp_ointbuf[ebp*2+4]
  455.         int 31h
  456.         sub di,1
  457.         jnc d_retreall0
  458.         jmp short d_exit
  459. ;─────────────────────────────────────────────────────────────────────────────
  460. d_exit16err:                            ; DPMI Exit with error message
  461.         mov ds:v86r_ds,code16
  462.         mov ds:v86r_ah,9
  463.         mov ax,300h
  464.         mov bx,21h
  465.         xor cx,cx
  466.         mov edi,offset ds:v86r_edi
  467.         push ds
  468.         pop es
  469.         int 31h
  470. ;─────────────────────────────────────────────────────────────────────────────
  471. d_exit:                                 ; DPMI exit to real mode
  472.         mov es,d_pspsel                 ; restore env selector
  473.         mov ax,d_oldenvsegsel
  474.         mov es:[2ch],ax
  475.         jmp exit
  476. ;═════════════════════════════════════════════════════════════════════════════
  477. d_start:                                ; Start in a crappy DPMI system
  478.         or ds:_sysbyte0,3               ; set system type DPMI byte
  479.  
  480.         test bl,1                       ; must be 32bit DPMI
  481.         mov dx,offset d_errmsg0
  482.         jz exit16err
  483.  
  484.         mov d_enterpmode[0],di          ; store enter addx
  485.         mov d_enterpmode[2],es
  486.         push word ptr fs:[2ch]          ; preserve old env seg
  487.  
  488.         movzx eax,si                    ; get mem for DPMI blok
  489.         shl eax,4
  490.         call pregetlomem
  491.         shr eax,4
  492.         add ax,code32
  493.         mov es,ax
  494.  
  495.         mov ax,1                        ; switch to pmode
  496.         call dword ptr d_enterpmode
  497.         cli                             ; I don't trust DPMI
  498.         mov dx,offset d_errmsg1
  499.         jc exit16err
  500.         mov ds:v86r_dx,dx               ; prepare for abort maybe
  501.         pop ax                          ; swap old env seg with selector
  502.         xchg ax,es:[2ch]
  503.         mov d_oldenvsegsel,ax
  504.         mov d_pspsel,es                 ; store stupid selectors
  505.         mov ds:data16sel,ds
  506.         mov ds:code16sel,cs
  507.         mov ds:code16off,offset d_retreal       ; set return to real mode addx
  508.         mov ds:_setirqvect,offset dp_setirq     ; modify some crap
  509.         mov ds:_getirqvect,offset dp_getirq
  510.  
  511.         push ds                         ; no more need for PSP
  512.         pop es
  513.         mov ax,3                        ; get selector increment value
  514.         int 31h
  515.         mov bx,ax
  516.         xor ax,ax                       ; get 3 needed descriptors
  517.         mov cx,3
  518.         int 31h
  519.         jc d_exit16err
  520.  
  521.         mov si,ax                       ; set up descriptors
  522.         mov ds:_selcode,ax
  523.         lea ecx,[eax+ebx]
  524.         mov ds:_seldata,cx
  525.         lea ebp,[ecx+ebx]
  526.         mov ds:_selzero,bp
  527.         mov ds:v86r_dx,offset d_errmsg2
  528.         mov ax,0ch                      ; set descriptors from GDT
  529.         mov bx,si
  530.         mov edi,offset ds:gdt32code32
  531.         or byte ptr [edi+5],60h
  532.         int 31h
  533.         jc d_exit16err
  534.         mov bx,cx
  535.         mov edi,offset ds:gdt32data32
  536.         or byte ptr [edi+5],60h
  537.         int 31h
  538.         jc d_exit16err
  539.         mov bx,bp
  540.         mov edi,offset ds:gdt32zero32
  541.         or byte ptr [edi+5],60h
  542.         int 31h
  543.         jc d_exit16err
  544.  
  545.         mov es,cx                       ; ES, FS, and GS what they should be
  546.         mov fs,cx
  547.         mov gs,bp
  548.  
  549.         mov edi,ds:_lomembase           ; chek and get extended memory
  550.         mov eax,ds:_lomemtop
  551.         sub eax,edi
  552.         cmp eax,48
  553.         mov ds:v86r_dx,offset errmsg1
  554.         jb d_exit16err
  555.         mov ax,500h
  556.         int 31h
  557.         mov eax,es:[edi+14h]
  558.         cmp eax,-1
  559.         jne short d_startf0
  560.         mov eax,(EXTMIN+3) shr 2
  561. d_startf0:
  562.         shl eax,12
  563.         mov edx,eax
  564.         shr eax,10
  565.         cmp eax,EXTMIN
  566.         mov ds:v86r_dx,offset errmsg3
  567.         jb d_exit16err
  568.         or edx,edx
  569.         jz short d_startf1
  570.         mov cx,dx
  571.         shld ebx,edx,16
  572.         mov ax,501h
  573.         int 31h
  574.         mov ds:v86r_dx,offset errmsg5
  575.         jc d_exit16err
  576.         shl ebx,16
  577.         mov bx,cx
  578.         sub ebx,ds:_code32a
  579.         mov ds:_himembase,ebx
  580.         add ebx,edx
  581.         mov ds:_himemtop,ebx
  582. d_startf1:
  583.  
  584.         mov ax,305h                     ; get save/restore state addxs
  585.         int 31h
  586.         mov ds:dp_savelen,ax
  587.         mov dword ptr ds:dp_saveaddx[0],edi
  588.         mov word ptr ds:dp_saveaddx[4],si
  589.         mov word ptr d_saveaddx[0],cx
  590.         mov word ptr d_saveaddx[2],bx
  591.         mov ax,306h                     ; get switch mode addxs
  592.         int 31h
  593.         mov dword ptr ds:dp_switchaddx[0],edi
  594.         mov word ptr ds:dp_switchaddx[4],si
  595.         mov word ptr d_switchaddx[0],cx
  596.         mov word ptr d_switchaddx[2],bx
  597.  
  598.         mov ax,400h                     ; set IRQ handlers to PIC values
  599.         int 31h
  600.         mov di,offset ds:intslotnum
  601.         xchg dl,dh
  602.         mov bx,dx
  603.         call setintslots
  604.  
  605.         mov ah,2                        ; backup and set all int vektorz
  606.         mov si,ds:_selcode
  607.         mov edi,17
  608. d_startl0:
  609.         mov bl,ds:intslotnum[di]
  610.         mov al,4
  611.         int 31h
  612.         lea ebp,[edi*2+edi]
  613.         mov dword ptr ds:dp_ointbuf[ebp*2],edx
  614.         mov word ptr ds:dp_ointbuf[ebp*2+4],cx
  615.         mov al,5
  616.         movzx edx,d_nintoff[edi*2]
  617.         mov cx,si
  618.         int 31h
  619.         sub di,1
  620.         jnc d_startl0
  621.  
  622.         mov eax,gs:[32h*4]              ; set real mode int32 handler
  623.         mov d_oint32vect,eax
  624.         db 65h,66h,0c7h,6       ; MOV DWORD PTR GS:[32h*4],code16:d_int32
  625.         dw 32h*4,d_int32,code16 ;
  626.         push es                         ; set up needed regs & go on to 32bit
  627.         pop ss
  628.         add esp,ds:realstackbase
  629. ;-----------------------------------------------------------------------------
  630. c_to32bit:                              ; shared by custom code
  631.         push es
  632.         pop ds
  633.         push dword ptr cs:_selcode
  634.         push offset p_start
  635.         db 66h,0cbh             ; 32bit RETF
  636.  
  637. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  638. ; 16 bit XMS system data
  639. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  640. x_calladdx      dd      ?               ; XMS driver addx
  641. x_handle        dw      ?               ; XMS handle of extended memory
  642.  
  643. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  644. ; 16 bit XMS system code
  645. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  646. ;─────────────────────────────────────────────────────────────────────────────
  647. x_exit:                                 ; XMS exit (clean up allocation)
  648.         mov dx,x_handle
  649.         mov ah,0dh
  650.         call x_calladdx
  651.         mov ah,0ah
  652.         call x_calladdx
  653.         jmp exit
  654. ;─────────────────────────────────────────────────────────────────────────────
  655. x_exiterr5:                             ; exit with error message 5
  656.         mov dx,offset errmsg5
  657.         jmp exit16err
  658. ;═════════════════════════════════════════════════════════════════════════════
  659. x_start:                                ; start in an XMS system
  660.         or ds:_sysbyte0,1               ; set system type XMS byte
  661.  
  662.         mov ax,4310h                    ; get XMS driver addx
  663.         int 2fh
  664.         mov word ptr x_calladdx[0],bx
  665.         mov word ptr x_calladdx[2],es
  666.  
  667.         mov ah,3                        ; XMS enable A20
  668.         call x_calladdx
  669.         or ax,ax
  670.         mov dx,offset errmsg4
  671.         jz exit16err
  672.  
  673.         mov ah,8                        ; chek and get extended memory
  674.         call x_calladdx
  675.         cmp ax,EXTMIN+64
  676.         mov dx,offset errmsg3
  677.         jb exit16err
  678.         lea edx,[eax-64]
  679.         movzx ecx,dx
  680.         shl ecx,10
  681.         mov ah,9
  682.         call x_calladdx
  683.         or ax,ax
  684.         jz x_exiterr5
  685.         mov x_handle,dx
  686.         mov exitrout,offset x_exit
  687.         mov ah,0ch
  688.         call x_calladdx
  689.         or ax,ax
  690.         jz x_exiterr5
  691.         shrd eax,edx,16
  692.         mov ax,bx
  693.         sub eax,ds:_code32a
  694.         mov ds:_himembase,eax
  695.         add eax,ecx
  696.         mov ds:_himemtop,eax
  697.  
  698.         jmp c_startf0                   ; go on to custom start
  699.  
  700. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  701. ; 16bit VCPI system data
  702. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  703. v_errmsg0       db      'Incompatible VCPI PIC mappings!!!',7,'$'
  704.  
  705. v_emmname       db      'EMMXXXX0',0    ; EMS device name
  706. v_emshandle     dw      ?               ; one page allocated to turn on
  707.  
  708. v_oint32vect    dd      ?               ; old real mode INT32 vektor
  709.  
  710. v_pagedirseg    dw      ?               ; seg of page directory
  711. v_pagebase      dw      0               ; first page of himem (*4)+1000h
  712. v_pagetop       dw      0               ; top page of himem (*4)+1000h
  713.  
  714. v_ss_cr3        dd      ?               ; new CR3 for pmode (physical)
  715. v_ss_gdtaddxptr dw      c_gdt32addx,0   ; ptr to GDT data for pmode
  716. v_ss_idtaddxptr dw      c_idt32addx,0   ; ptr to IDT data for pmode
  717. v_ss_ldtsel     dw      0               ; don't need no stinkin LDTs
  718. v_ss_trsel      dw      30h             ; task state segment selector
  719. v_ss_dest       dd      ?               ; start in pmode EIP
  720.                 dw      20h             ; start in pmode CS
  721.  
  722. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  723. ; 16bit VCPI system code
  724. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  725. ;═════════════════════════════════════════════════════════════════════════════
  726. v_retreal:                              ; VCPI return to real mode
  727.         mov ebx,esp
  728.         sub ebx,ds:realstackbase
  729.         mov eax,code16
  730.         push eax
  731.         push eax
  732.         push eax
  733.         push eax
  734.         push eax
  735.         push ebx
  736.         pushfd
  737.         push eax
  738.         dw 6866h,v_retreal2,0   ; 32bit PUSH offset v_retreal2
  739.         mov ax,gs
  740.         mov ds,ax
  741.         mov ax,0de0ch
  742.         call cs:vp_vcpientryaddx
  743. ;═════════════════════════════════════════════════════════════════════════════
  744. v_retreal2:                             ; in real (V86) mode from VCPI
  745.         mov bx,c_oldpicvectors
  746.         call set8259vektorz
  747.         movzx cx,bh
  748.         xor bh,bh
  749.         mov ax,0de0bh
  750.         int 67h
  751.         xor ax,ax                       ; restore INT 32 vektor
  752.         mov es,ax
  753.         mov eax,v_oint32vect
  754.         mov es:[32h*4],eax
  755.         jmp c_retreal2
  756. ;═════════════════════════════════════════════════════════════════════════════
  757. v_int32:                                ; VCPI real INT32: EDX=off
  758.         mov eax,offset vp_callpmode
  759. ;─────────────────────────────────────────────────────────────────────────────
  760. ; EAX=offset to jump to in code32
  761. v_switchtopmode:                        ; VCPI switch to pmode
  762.         mov cs:v_ss_dest,eax
  763.         mov esi,offset v_ss_cr3
  764.         add esi,cs:_code16a
  765.         mov ax,0de0ch
  766.         int 67h
  767. ;─────────────────────────────────────────────────────────────────────────────
  768. v_exit2:                                ; VCPI exit (clean up pages)
  769.         mov es,v_pagedirseg
  770.         mov si,v_pagebase
  771.         mov cx,v_pagetop
  772.         sub cx,si
  773.         jz short v_exit
  774. v_exit2l0:
  775.         mov edx,es:[si]
  776.         and dx,0f000h
  777.         mov ax,0de05h
  778.         int 67h
  779.         add si,4
  780.         sub cx,4
  781.         jnz v_exit2l0
  782. ;─────────────────────────────────────────────────────────────────────────────
  783. v_exit:                                 ; VCPI exit (clean up EMS page)
  784.         mov ah,45h
  785.         mov dx,v_emshandle
  786.         int 67h
  787.         jmp exit
  788. ;─────────────────────────────────────────────────────────────────────────────
  789. v_exiterr1:                             ; VCPI not enough low mem exit
  790.         mov dx,offset errmsg1
  791.         jmp exit16err
  792. ;═════════════════════════════════════════════════════════════════════════════
  793. v_start:                                ; start continues from VCPI
  794.         or ds:_sysbyte0,2               ; set system type VCPI byte
  795.         mov exitrout,offset v_exit      ; set EMS cleanup exit
  796.         mov ds:code16off,offset v_retreal       ; set VCPI return to real mode
  797.  
  798.         mov ax,0de0ah                   ; get PIC mappings
  799.         int 67h
  800.         mov bh,cl
  801.         mov c_oldpicvectors,bx
  802.         mov dx,offset v_errmsg0         ; chek for compatible PIC mapping
  803.         cmp bl,bh
  804.         je exit16err
  805.         cmp bl,30h
  806.         je exit16err
  807.         cmp bh,30h
  808.         je exit16err
  809.         mov ax,2ch                      ; compatible, get highest needed num
  810.         cmp al,bl
  811.         ja short v_startf1
  812.         mov al,bl
  813. v_startf1:
  814.         cmp al,bh
  815.         ja short v_startf2
  816.         mov al,bh
  817. v_startf2:
  818.         add al,7
  819.         mov c_numofintvects,al
  820.         lea eax,[eax*8+7]               ; set limit of IDT
  821.         mov c_idt32addx,ax
  822.         mov di,offset ds:intslotnum     ; set int slots needed
  823.         call setintslots
  824.  
  825. v_startf0:
  826.         movzx eax,c_idt32addx           ; get IDT size -1
  827.         add eax,68h+1
  828.         call pregetlomem                ; allocate TSS and IDT
  829.         mov ebp,ds:_code32a             ; TSS location in mem to GDT
  830.         lea ebx,[eax+ebp]
  831.         or dword ptr ds:gdt32task[2],ebx
  832.         add ebx,68h                     ; set up IDT addx
  833.         mov dword ptr c_idt32addx[2],ebx
  834.         mov eax,ds:_code16a             ; adjust mode switch structure
  835.         add dword ptr v_ss_gdtaddxptr,eax
  836.         add dword ptr v_ss_idtaddxptr,eax
  837.  
  838.         mov exitrout,offset v_exit2     ; set VCPI cleanup exit
  839.  
  840.         mov eax,ds:_lomembase           ; align lomem base on a page
  841.         mov ebx,ds:_code32a
  842.         add ebx,eax
  843.         lea ecx,[ebx+0fffh]
  844.         and ecx,0fffff000h
  845.         sub ebx,ecx
  846.         sub eax,ebx
  847.         mov ds:_lomembase,eax
  848.         mov ebp,ds:_lomemtop            ; get available low memory
  849.         sub ebp,eax
  850.         sub ebp,LOWMIN*1024             ; die if not enough
  851.         jc v_exiterr1
  852.         cmp ebp,8192
  853.         jb v_exiterr1
  854.  
  855.         shld eax,ecx,28                 ; get segment and clear all pages
  856.         mov v_pagedirseg,ax
  857.         mov es,ax
  858.         xor di,di
  859.         mov cx,2048
  860.         xor eax,eax
  861.         rep stos dword ptr es:[di]
  862.         mov di,1000h                    ; get VCPI pmode interface
  863.         mov si,offset ds:gdt32vcpi
  864.         mov ax,0de01h
  865.         int 67h
  866.         mov dword ptr ds:vp_vcpientryaddx,ebx
  867.  
  868.         mov v_pagebase,di               ; set up and go through allocation
  869.         mov v_pagetop,di
  870.         movzx eax,di
  871.         sub eax,1000h
  872.         shl eax,10
  873.         mov ebp,ds:_code32a
  874.         sub eax,ebp
  875.         mov ds:_himembase,eax
  876.         mov ebx,8192
  877. v_startl2:
  878.         mov ax,0de04h
  879.         int 67h
  880.         or ah,ah
  881.         jnz short v_startl2d
  882.         test di,0fffh
  883.         jnz short v_startf4
  884.         add ebx,4096
  885.         cmp ebx,ebp
  886.         ja v_exiterr1
  887. v_startf4:
  888.         and dx,0f000h
  889.         or dl,7
  890.         mov es:[di],edx
  891.         add di,4
  892.         jnc v_startl2
  893. v_startl2d:
  894.         mov v_pagetop,di
  895.         lea si,[di-1000h]
  896.         movzx eax,si
  897.         shl eax,10
  898.         sub eax,ebp             ; EBP=_code32a
  899.         mov ds:_himemtop,eax
  900.         sub di,v_pagebase
  901.         cmp di,EXTMIN
  902.         mov dx,offset errmsg3
  903.         jb exit16err
  904.         add ds:_lomembase,ebx
  905.  
  906.         movzx ebx,v_pagedirseg          ; set up physical addresses
  907.         shr ebx,8
  908.         mov eax,es:[ebx*4+1000h]
  909.         mov v_ss_cr3,eax
  910.         xor di,di
  911. v_startl3:
  912.         inc ebx
  913.         mov eax,es:[ebx*4+1000h]
  914.         and ax,0f000h
  915.         or al,7
  916.         stos dword ptr es:[di]
  917.         sub si,1000h
  918.         ja v_startl3
  919.  
  920.         xor ax,ax                       ; set VCPI real mode INT32
  921.         mov es,ax
  922.         mov eax,es:[32h*4]
  923.         mov v_oint32vect,eax
  924.         db 26h,66h,0c7h,6       ; MOV DWORD PTR ES:[32h*4],code16:d_int32
  925.         dw 32h*4,d_int32,code16 ;
  926.         mov di,offset ds:cp_int3_m0     ; modify INT32/33 custom pmode handler
  927.         mov byte ptr [di],0e9h
  928.         mov dword ptr [di+1],VCPIINT3_M0
  929.         mov di,offset d_int32m0         ; modify INT32 DPMI real handler
  930.         mov byte ptr [di],0e9h
  931.         mov word ptr [di+1],VCPIINT32M0
  932.         mov di,offset ds:dp_callpmodem1 ; modify INT32/33 DPMI pmode call
  933.         mov byte ptr [di],0e9h
  934.         mov dword ptr [di+1],VCPIINT32M1
  935.  
  936.         mov eax,offset v_startf3        ; offset to jump to in pmode
  937.         jmp v_switchtopmode             ; duh?
  938. ;-----------------------------------------------------------------------------
  939. v_startf3:                              ; in 16bit pmode
  940.         mov di,offset v_startf5         ; set up segregs and stack
  941.         jmp setpmoderegs
  942. v_startf5:
  943.         mov word ptr v_ss_dest[4],8     ; only enter 32bit pmode from now on
  944.         mov ecx,offset c_idt32handler   ; int handler table
  945.         mov dx,0db87h                   ; XCHG BX,BX for ret to pmode thing
  946.         mov edi,dword ptr c_idt32addx[2]; get ptr to IDT
  947.         sub edi,ds:_code32a
  948.         jmp c_startf2                   ; continue in custom start
  949.  
  950. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  951. ; 16 bit custom system data
  952. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  953. c_idt16addx     dw      3ffh, 0,0       ; default real mode IDT addx&limit
  954. c_idt32addx     dw      19fh, ?,?       ; 32bit IDT addx&limit
  955. c_gdt32addx     dw      04fh, gdt32,0   ; 32bit GDT addx&limit
  956.  
  957. c_oldpicvectors dw      7008h           ; old PIC vals, maybe modified in VCPI
  958. c_numofintvects db      33h             ; number of int vects needed -1, ditto
  959.  
  960. c_idt32handler  dw      cp_irq0,cp_irq1,cp_irq2,cp_irq3,cp_irq4,cp_irq5
  961.                 dw      cp_irq6,cp_irq7,cp_irq8,cp_irq9,cp_irqa,cp_irqb
  962.                 dw      cp_irqc,cp_irqd,cp_irqe,cp_irqf
  963.                 dw      cp_int33,cp_int32,cp_int31
  964.                 dw      cp_exc0,cp_exc1,cp_exc2,cp_exc3,cp_exc4,cp_exc5
  965.                 dw      cp_exc6,cp_exc7,cp_exc8,cp_exc9,cp_exca,cp_excb
  966.                 dw      cp_excc,cp_excd,cp_exce
  967.  
  968. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  969. ; 16 bit custom system code
  970. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  971. ;═════════════════════════════════════════════════════════════════════════════
  972. c_irqreal:                              ; custom real mode IRQ from pmode
  973.         pushf
  974.         push cs
  975.         push offset icrealret
  976.         jmp cs:tempaddx
  977. ;═════════════════════════════════════════════════════════════════════════════
  978. c_retreal:                              ; custom return to real mode
  979.         mov ax,ds
  980.         mov es,ax
  981.         mov fs,ax
  982.         mov gs,ax
  983.         mov ss,ax
  984.         lidt fword ptr c_idt16addx
  985.         mov eax,cr0
  986.         and al,0feh
  987.         mov cr0,eax
  988.         db 0eah
  989.         dw c_retreal2,code16
  990. ;═════════════════════════════════════════════════════════════════════════════
  991. c_retreal2:                             ; in real mode from custom or VCPI
  992.         mov ax,code16
  993.         mov ds,ax
  994.         mov es,ax
  995.         mov fs,ax
  996.         mov gs,ax
  997.         sub ax,10h
  998.         mov ss,ax
  999.         mov esp,100h
  1000.         push exitrout
  1001.         mov bx,c_oldpicvectors          ; restore int controllers
  1002.         jmp set8259vektorz
  1003. ;═════════════════════════════════════════════════════════════════════════════
  1004. c_start:                                ; start in custom system
  1005.         call enableA20                  ; enable that stupid A20 thingy
  1006.  
  1007.         mov ah,88h                      ; chek and get extended mem
  1008.         int 15h
  1009.         cmp ax,EXTMIN
  1010.         mov dx,offset errmsg3
  1011.         jb exit16err
  1012.         movzx eax,ax
  1013.         shl eax,10
  1014.         mov ebx,100000h
  1015.         sub ebx,ds:_code32a
  1016.         mov ds:_himembase,ebx
  1017.         add eax,ebx
  1018.         mov ds:_himemtop,eax
  1019. ;═════════════════════════════════════════════════════════════════════════════
  1020. c_startf0:                              ; start continues from custom or XMS
  1021.         mov eax,2208h                   ; allocate TSS, IO bitmap, and IDT
  1022.         call pregetlomem
  1023.         push eax
  1024.         mov bx,2820h                    ; new base vektorz for int controllers
  1025.         call set8259vektorz
  1026.         pop ebx
  1027.         lgdt fword ptr c_gdt32addx      ; switch to pmode
  1028.         mov eax,cr0
  1029.         or al,1
  1030.         mov cr0,eax
  1031.         db 0eah
  1032.         dw c_startf1,20h
  1033. ;-----------------------------------------------------------------------------
  1034. c_startf1:                              ; in 16bit pmode
  1035.         mov di,offset c_startf3         ; set up segregs and stack
  1036.         jmp setpmoderegs
  1037. c_startf3:
  1038.         lea eax,[ebx+4]                 ; addx of ESP0 in TSS
  1039.         mov ds:cp_tssesp0ptr,eax
  1040.         mov ebp,ds:_code32a             ; TSS location in mem to GDT
  1041.         lea eax,[ebx+ebp]
  1042.         or dword ptr ds:gdt32task[2],eax
  1043.         add eax,2068h                   ; set up IDT addx
  1044.         mov ecx,offset c_idt32addx
  1045.         mov dword ptr [ecx+2],eax
  1046.         lidt fword ptr [ecx]
  1047.         mov ax,30h                      ; load task register
  1048.         ltr ax
  1049.  
  1050.         mov dword ptr es:[ebx+8],10h    ; set up TSS stuff (EBX -> TSS)
  1051.         mov edi,104
  1052.         mov es:[ebx+102],di
  1053.         mov word ptr es:[ebx+100],0
  1054.         add edi,ebx                     ; fill IO bitmap with 0
  1055.         xor eax,eax
  1056.         mov ecx,800h
  1057.         rep stos dword ptr es:[edi]
  1058.         mov ecx,offset c_idt32handler   ; int handler table
  1059.         mov dx,0ffcdh                   ; INT FF for ret to pmode thing
  1060. ;═════════════════════════════════════════════════════════════════════════════
  1061. ; ECX->int vect table, EDI->IDT, DX=word for icrealret
  1062. c_startf2:                              ; start continues from custom or VCPI
  1063.         mov icrealret,dx                ; modify pmode return from real thingy
  1064.         mov ds:cp_idt32ptr,edi          ; set up IDT entries
  1065.         movzx esi,c_numofintvects
  1066. c_startl0:
  1067.         mov dword ptr es:[edi+esi*8],80000h+offset cp_excf
  1068.         mov dword ptr es:[edi+esi*8+4],8e00h
  1069.         sub si,1
  1070.         jnc c_startl0
  1071.         mov esi,33
  1072. c_startl1:
  1073.         movzx ebp,ds:intslotnum[si]
  1074.         mov ax,[ecx+esi*2]
  1075.         mov es:[edi+ebp*8],ax
  1076.         sub si,1
  1077.         jnc c_startl1
  1078.  
  1079.         pushfd                          ; set eflags: NT=0, IOPL=3
  1080.         pop eax
  1081.         and ah,0bfh
  1082.         or ah,30h
  1083.         push eax
  1084.         popfd
  1085.  
  1086.         jmp c_to32bit                   ; jump to jump to 32bit code
  1087.  
  1088. code16  ends
  1089.  
  1090. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  1091. ; 32bit pmode code
  1092. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  1093. code32  segment para public use32
  1094.         assume cs:code32, ds:code32
  1095.         org 0
  1096.  
  1097. extrn   _main:near
  1098.  
  1099. public  _exit, _ret, _getmem, _getlomem, _gethimem, _lomemsize, _himemsize
  1100. public  _getirqmask, _setirqmask
  1101.  
  1102. public  v86r_eax, v86r_ebx, v86r_ecx, v86r_edx, v86r_esi, v86r_edi, v86r_ebp
  1103. public  v86r_ax, v86r_bx, v86r_cx, v86r_dx, v86r_si, v86r_di, v86r_bp
  1104. public  v86r_al, v86r_ah, v86r_bl, v86r_bh, v86r_cl, v86r_ch, v86r_dl, v86r_dh
  1105. public  v86r_ds, v86r_es, v86r_fs, v86r_gs
  1106. public  _selcode, _seldata, _selzero, _lomembase, _lomemtop, _himembase
  1107. public  _himemtop, _pspa, _code16a, _code32a, _getirqvect, _setirqvect
  1108. public  _sysbyte0
  1109.  
  1110. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1111. ; 32 bit common system data
  1112. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1113.                 dd      ?               ; scratch dword for VCPI tss esp0
  1114. _lomembase      dd      ?               ; low mem base for allocation
  1115. _lomemtop       dd      ?               ; top of low mem
  1116. _himembase      dd      0               ; high mem base for allocation
  1117. _himemtop       dd      0               ; top of high mem
  1118. _pspa           dd      ?               ; offset of start of PSP from 0
  1119. _code16a        dd      ?               ; offset of start of 16bit code from 0
  1120. _code32a        dd      ?               ; offset of start of 32bit code from 0
  1121. _selcode        dw      8               ; code segment selector
  1122. _seldata        dw      10h             ; data segment alias for code
  1123. _selzero        dw      18h             ; data segment starting at 0:0
  1124. _sysbyte0       db      0               ; system bits:
  1125.                                         ;  0-1: 0=raw, 1=XMS, 2=VCPI, 3=DPMI
  1126.  
  1127. _getirqvect     dd      cp_getirq       ; get IRQ handler offset routine addx
  1128. _setirqvect     dd      cp_setirq       ; set IRQ handler offset routine addx
  1129.  
  1130. gdt32           dq      0
  1131. gdt32code32     db      0ffh,0ffh,0,0,0,9ah,0cfh,0
  1132. gdt32data32     db      0ffh,0ffh,0,0,0,92h,0cfh,0
  1133. gdt32zero32     db      0ffh,0ffh,0,0,0,92h,0cfh,0
  1134. gdt32code16     db      0ffh,0ffh,0,0,0,9ah,0,0
  1135. gdt32data16     db      0ffh,0ffh,0,0,0,92h,0,0
  1136. gdt32task       db      0ffh,0ffh,0,0,0,89h,0,0
  1137. gdt32vcpi       dq      3 dup(?)
  1138.  
  1139. v86r_edi        label   dword           ; vregs for pmode<>real communication
  1140. v86r_di         dw      ?, ?            ;  needz to stay this way cuz its a
  1141. v86r_esi        label   dword           ;  stupid DPMI structure thingy
  1142. v86r_si         dw      ?, ?
  1143. v86r_ebp        label   dword
  1144. v86r_bp         dw      ?, ?
  1145.                 dd      0
  1146. v86r_ebx        label   dword
  1147. v86r_bx         label   word
  1148. v86r_bl         db      ?
  1149. v86r_bh         db      ?, ?,?
  1150. v86r_edx        label   dword
  1151. v86r_dx         label   word
  1152. v86r_dl         db      ?
  1153. v86r_dh         db      ?, ?,?
  1154. v86r_ecx        label   dword
  1155. v86r_cx         label   word
  1156. v86r_cl         db      ?
  1157. v86r_ch         db      ?, ?,?
  1158. v86r_eax        label   dword
  1159. v86r_ax         label   word
  1160. v86r_al         db      ?
  1161. v86r_ah         db      ?, ?,?
  1162. v86r_flags      dw      ?
  1163. v86r_es         dw      ?
  1164. v86r_ds         dw      ?
  1165. v86r_fs         dw      ?
  1166. v86r_gs         dw      ?
  1167.                 dd      0,0
  1168.  
  1169. oint1bvect      dd      ?               ; old int 1bh vektor (ctrl+break)
  1170. oirqmask        dw      ?               ; old port 21h and 0a1h masks
  1171. intslotnum      db      20h,21h,22h,23h,24h,25h,26h,27h,28h,29h,2ah,2bh,2ch,2dh,2eh,2fh
  1172.                 db      33h,32h,31h,0,1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh
  1173.  
  1174. code16off       dw      c_retreal       ; offset in 16bit of exit function
  1175. code16sel       dw      20h             ; 16bit pmode code selector
  1176. data16sel       dw      28h             ; 16bit pmode data selector
  1177.  
  1178. nextmodestack   dw      (STAKLEN-STAKSAFE)*16   ; stack for next mode switch
  1179. tempaddx        dd      ?               ; temporary xfer addx, seg:off or off
  1180. realstackbase   dd      ?               ; linear ptr to beginning of codeend
  1181.  
  1182. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1183. ; 32 bit common system code
  1184. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1185. ;═════════════════════════════════════════════════════════════════════════════
  1186. ; BX -> real mode offset of int32 handler
  1187. p_start:                                ; common 32bit start
  1188.         mov eax,gs:[1bh*4]              ; neutralize crtl+break
  1189.         mov oint1bvect,eax
  1190.         db 65h,67h,0c7h,6       ; MOV DWORD PTR GS:[1bh*4],code16:nullint
  1191.         dw 1bh*4,nullint,code16 ;
  1192.         in al,21h                       ; save old PIC masks
  1193.         mov ah,al
  1194.         in al,0a1h
  1195.         mov oirqmask,ax
  1196.         jmp _main                       ; go to main code
  1197.  
  1198. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1199. ; Allocate any mem, (first cheks low, then high)
  1200. ; In:
  1201. ;   EAX - size requested
  1202. ; Out:
  1203. ;   CF=0 - memory allocated
  1204. ;   CF=1 - not enough mem
  1205. ;   EAX - linear pointer to mem or ?
  1206. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1207. _getmem:
  1208.         push eax
  1209.         call _getlomem
  1210.         jnc short getmemd
  1211.         pop eax
  1212.         jmp short _gethimem
  1213. getmemd:
  1214.         add esp,4
  1215. _ret:                                   ; generic RET instruction
  1216.         ret
  1217. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1218. ; Allocate some low mem
  1219. ; In:
  1220. ;   EAX - size requested
  1221. ; Out:
  1222. ;   CF=0 - memory allocated
  1223. ;   CF=1 - not enough mem
  1224. ;   EAX - linear pointer to mem or ?
  1225. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1226. _getlomem:
  1227.         add eax,_lomembase
  1228.         cmp eax,_lomemtop
  1229.         ja short getmemerr
  1230.         xchg eax,_lomembase
  1231.         clc
  1232.         ret
  1233. getmemerr:
  1234.         stc
  1235.         ret
  1236. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1237. ; Allocate some high mem
  1238. ; In:
  1239. ;   EAX - size requested
  1240. ; Out:
  1241. ;   CF=0 - memory allocated
  1242. ;   CF=1 - not enough mem
  1243. ;   EAX - linear pointer to mem or ?
  1244. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1245. _gethimem:
  1246.         add eax,_himembase
  1247.         cmp eax,_himemtop
  1248.         ja short getmemerr
  1249.         xchg eax,_himembase
  1250.         clc
  1251.         ret
  1252. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1253. ; Get amount of free low mem
  1254. ; Out:
  1255. ;   EAX - number of bytes free
  1256. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1257. _lomemsize:
  1258.         mov eax,_lomemtop
  1259.         sub eax,_lomembase
  1260.         ret
  1261. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1262. ; Get amount of free high mem
  1263. ; Out:
  1264. ;   EAX - number of bytes free
  1265. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1266. _himemsize:
  1267.         mov eax,_himemtop
  1268.         sub eax,_himembase
  1269.         ret
  1270. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1271. ; Get status of IRQ mask bit
  1272. ; In:
  1273. ;   BL - IRQ num (0-15)
  1274. ; Out:
  1275. ;   AL - status: 0=enabled, 1=disabled
  1276. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1277. _getirqmask:
  1278.         push ax
  1279.         in al,0a1h
  1280.         mov ah,al
  1281.         in al,21h
  1282.         xchg cl,bl
  1283.         shr ax,cl
  1284.         xchg cl,bl
  1285.         and al,1
  1286.         mov [esp],al
  1287.         pop ax
  1288.         ret
  1289. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1290. ; Set status of IRQ mask bit
  1291. ; In:
  1292. ;   BL - IRQ num (0-15)
  1293. ;   AL - status: 0=enabled, 1=disabled
  1294. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1295. _setirqmask:
  1296.         push ax bx cx dx
  1297.         mov cl,bl
  1298.         mov bx,0fffeh
  1299.         movzx dx,al
  1300.         rol bx,cl
  1301.         shl dx,cl
  1302.         in al,0a1h
  1303.         mov ah,al
  1304.         in al,21h
  1305.         and ax,bx
  1306.         or ax,dx
  1307.         out 21h,al
  1308.         mov al,ah
  1309.         out 0a1h,al
  1310.         pop dx cx bx ax
  1311.         ret
  1312. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1313. ; Exit to real mode
  1314. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1315. _exit:
  1316.         cli
  1317.         mov eax,oint1bvect              ; restore ctrl+break
  1318.         mov gs:[1bh*4],eax
  1319.         mov ax,oirqmask                 ; restore PIC masks
  1320.         out 0a1h,al
  1321.         mov al,ah
  1322.         out 21h,al
  1323.         push code16sel                  ; go to 16bit pmode exit code
  1324.         push code16off
  1325.         mov ds,data16sel
  1326.         db 66h,0cbh             ; 16bit RETF
  1327.  
  1328. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1329. ; 32 bit DPMI system data
  1330. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1331. dp_switchaddx   df      ?               ; switch to real mode addx
  1332. dp_saveaddx     df      ?               ; save/restore state addx
  1333. dp_savelen      dw      0,0             ; length of state buffer
  1334. dp_savedstakoff dd      ?               ; current saved stack offset
  1335. dp_savedstaksel dw      ?               ; current saved stack selector
  1336.  
  1337. dp_ointbuf      df      18 dup(?)       ; saved interrupt addx buffer
  1338.  
  1339. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1340. ; 32 bit DPMI system code
  1341. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1342. ;═════════════════════════════════════════════════════════════════════════════
  1343. vp_callpmode:                           ; VCPI pmode call from real mode
  1344.         mov esp,ebx
  1345.         mov ax,10h
  1346.         mov ds,ax
  1347.         mov es,ax
  1348.         mov ss,ax
  1349. ;═════════════════════════════════════════════════════════════════════════════
  1350. dp_callpmode:                           ; DPMI pmode call from real mode
  1351.         cld
  1352.         mov ax,ds
  1353.         mov fs,ax
  1354.         mov gs,_selzero
  1355.         mov eax,v86r_eax
  1356.         mov ecx,v86r_ecx
  1357.         mov edx,v86r_edx
  1358.         mov ebx,v86r_ebx
  1359.         mov esi,v86r_esi
  1360.         mov edi,v86r_edi
  1361.         mov ebp,v86r_ebp
  1362.         push offset dp_callpmoded
  1363.         push tempaddx
  1364. dp_callpmodeif  db      ?       ; CLI or STI
  1365.         ret
  1366. dp_callpmoded:
  1367.         cli
  1368.         pushf
  1369.         pop v86r_flags
  1370.         mov v86r_eax,eax
  1371.         mov v86r_ecx,ecx
  1372.         mov v86r_edx,edx
  1373.         mov v86r_ebx,ebx
  1374.         mov v86r_esi,esi
  1375.         mov v86r_edi,edi
  1376.         mov v86r_ebp,ebp
  1377.         mov ecx,_code16a
  1378.         movzx ebx,gs:d_savedstakoff[ecx]
  1379.         mov dx,gs:d_savedstakseg[ecx]
  1380.         mov ax,code16
  1381. dp_callpmodem1:                         ; modified under VCPI
  1382. VCPIINT32M1=(vp_callpmoded-5)-$         ;
  1383.         mov cx,dx
  1384.         mov si,ax
  1385.         mov edi,offset d_int32d
  1386.         jmp dp_switchaddx
  1387. ;-----------------------------------------------------------------------------
  1388. vp_callpmoded:                          ; VCPI done with pmode call
  1389.         push eax
  1390.         push eax
  1391.         push eax
  1392.         push eax
  1393.         push edx
  1394.         push ebx
  1395.         pushfd
  1396.         push eax
  1397.         db 68h                          ; 32bit PUSH offset v_retreal2
  1398.         dw d_int32d2,0                  ;
  1399.         mov ax,gs
  1400.         mov ds,ax
  1401.         mov ax,0de0ch
  1402.         call cs:vp_vcpientryaddx
  1403. ;═════════════════════════════════════════════════════════════════════════════
  1404. dp_int32:                               ; DPMI INT 32h: CX:DX=seg:off
  1405.         pushad
  1406.         shl ecx,16
  1407.         mov cx,dx
  1408.         mov bp,offset callreal
  1409.         mov dl,1
  1410.         jmp short dp_int3_
  1411. ;═════════════════════════════════════════════════════════════════════════════
  1412. dp_int33:                               ; DPMI INT 33h: AL=int num
  1413.         pushad
  1414.         movzx eax,al
  1415.         mov ecx,gs:[eax*4]
  1416.         mov bp,offset intreal
  1417.         xor dl,dl
  1418. ;-----------------------------------------------------------------------------
  1419. dp_int3_:                               ; int or call to real mode
  1420.         mov ax,900h
  1421.         int 31h
  1422.         mov tempaddx,ecx
  1423.         push ax
  1424.         and al,dl
  1425.         add al,0fah
  1426.         mov ecx,_code16a
  1427.         mov gs:icrealif[ecx],al
  1428.         push dp_savedstakoff
  1429.         push dp_savedstaksel
  1430.         movzx ebx,nextmodestack
  1431.         lea eax,[ebx-STAKSAFE*16]
  1432.         mov nextmodestack,ax
  1433.         mov ax,ss
  1434.         mov es,ax
  1435.         sub esp,dword ptr dp_savelen
  1436.         mov edi,esp
  1437.         xor al,al
  1438.         call dp_saveaddx
  1439.         mov dp_savedstakoff,esp
  1440.         mov dp_savedstaksel,ss
  1441.         mov dx,codeend
  1442.         mov ax,v86r_ds
  1443.         mov cx,v86r_es
  1444.         movzx edi,bp
  1445.         mov si,code16
  1446.         jmp dp_switchaddx
  1447. dp_int3_d:
  1448.         mov edi,esp
  1449.         mov al,1
  1450.         call dp_saveaddx
  1451.         add esp,dword ptr dp_savelen
  1452.         pop dp_savedstaksel
  1453.         pop dp_savedstakoff
  1454.         add nextmodestack,STAKSAFE*16
  1455.         mov bx,v86r_flags
  1456.         mov ax,[esp+42]
  1457.         and ax,not 8d5h
  1458.         and bx,8d5h
  1459.         or ax,bx
  1460.         mov [esp+42],ax
  1461.         pop ax
  1462.         mov ah,9
  1463.         int 31h
  1464.         mov ax,ds
  1465.         mov es,ax
  1466.         mov fs,ax
  1467.         mov gs,_selzero
  1468.         popad
  1469.         iretd
  1470. ;═════════════════════════════════════════════════════════════════════════════
  1471. ; DPMI IRQ redirectors (needed to make all IRQ vector selectors = CS)
  1472. dp_irq0:
  1473.         jmp cs:dp_ointbuf[0]
  1474. dp_irq1:
  1475.         jmp cs:dp_ointbuf[6]
  1476. dp_irq2:
  1477.         jmp cs:dp_ointbuf[12]
  1478. dp_irq3:
  1479.         jmp cs:dp_ointbuf[18]
  1480. dp_irq4:
  1481.         jmp cs:dp_ointbuf[24]
  1482. dp_irq5:
  1483.         jmp cs:dp_ointbuf[30]
  1484. dp_irq6:
  1485.         jmp cs:dp_ointbuf[36]
  1486. dp_irq7:
  1487.         jmp cs:dp_ointbuf[42]
  1488. dp_irq8:
  1489.         jmp cs:dp_ointbuf[48]
  1490. dp_irq9:
  1491.         jmp cs:dp_ointbuf[54]
  1492. dp_irqa:
  1493.         jmp cs:dp_ointbuf[60]
  1494. dp_irqb:
  1495.         jmp cs:dp_ointbuf[66]
  1496. dp_irqc:
  1497.         jmp cs:dp_ointbuf[72]
  1498. dp_irqd:
  1499.         jmp cs:dp_ointbuf[78]
  1500. dp_irqe:
  1501.         jmp cs:dp_ointbuf[84]
  1502. dp_irqf:
  1503.         jmp cs:dp_ointbuf[90]
  1504.  
  1505. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1506. ; DPMI get IRQ handler offset
  1507. ; In:
  1508. ;   BL - IRQ num (0-0fh)
  1509. ; Out:
  1510. ;   EDX - offset of IRQ handler
  1511. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1512. dp_getirq:
  1513.         push ax bx cx
  1514.         movzx bx,bl
  1515.         mov bl,intslotnum[bx]
  1516.         mov ax,204h
  1517.         int 31h
  1518.         pop cx bx ax
  1519.         ret
  1520. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1521. ; DPMI set IRQ handler offset
  1522. ; In:
  1523. ;   BL - IRQ num (0-0fh)
  1524. ;   EDX - offset of IRQ handler
  1525. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1526. dp_setirq:
  1527.         push ax bx cx
  1528.         movzx bx,bl
  1529.         mov bl,intslotnum[bx]
  1530.         mov cx,cs
  1531.         mov ax,205h
  1532.         int 31h
  1533.         pop cx bx ax
  1534.         ret
  1535.  
  1536. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1537. ; 32 bit VCPI system data
  1538. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1539. vp_vcpientryaddx df      3800000000h    ; VCPI entry point in pmode
  1540.  
  1541. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1542. ; 32 bit VCPI system code
  1543. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1544. ;═════════════════════════════════════════════════════════════════════════════
  1545. vp_int3_:                               ; VCPI int or call to real mode
  1546.         mov ax,18h                      ; VCPI switch to real mode routine
  1547.         mov ds,ax
  1548.         mov ax,0de0ch
  1549.         call cs:vp_vcpientryaddx
  1550.  
  1551. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1552. ; 32 bit custom system data
  1553. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1554. cp_tssesp0ptr   dd      0               ; ptr to ESP0 in TSS, or null in VCPI
  1555. cp_idt32ptr     dd      ?               ; ptr to 32bit IDT
  1556.  
  1557. cp_v86irqnum    db      ?               ; int num of IRQ for V86 mode
  1558. cp_savedstakoff dd      ?               ; current saved stack offset
  1559.  
  1560. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1561. ; 32 bit custom system code
  1562. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1563. ;═════════════════════════════════════════════════════════════════════════════
  1564. cp_int31:                               ; INT 31h: AX=900h,901h,902h
  1565.         cmp al,1
  1566.         mov al,[esp+9]
  1567.         jb short cp_int31f0
  1568.         ja short cp_int31f1
  1569.         or byte ptr [esp+9],2
  1570.         jmp short cp_int31f1
  1571. cp_int31f0:
  1572.         and byte ptr [esp+9],0fdh
  1573. cp_int31f1:
  1574.         shr al,1
  1575.         and al,1
  1576.         iretd
  1577. ;═════════════════════════════════════════════════════════════════════════════
  1578. cp_int32:                               ; INT 32h: CX:DX=seg:off
  1579.         pushad
  1580.         shl ecx,16
  1581.         mov cx,dx
  1582.         mov ebp,offset callreal
  1583.         mov dl,1
  1584.         jmp short cp_int3_
  1585. ;═════════════════════════════════════════════════════════════════════════════
  1586. cp_int33:                               ; INT 33h: AL=int num
  1587.         pushad
  1588.         movzx eax,al
  1589.         mov ecx,gs:[eax*4]
  1590.         mov ebp,offset intreal
  1591.         xor dl,dl
  1592. ;-----------------------------------------------------------------------------
  1593. cp_int3_:                               ; int or call to real mode
  1594.         mov tempaddx,ecx
  1595.         mov edi,[esp+40]
  1596.         shld eax,edi,23
  1597.         and al,dl
  1598.         add al,0fah
  1599.         mov ecx,_code16a
  1600.         mov gs:icrealif[ecx],al
  1601.         movzx esi,nextmodestack
  1602.         lea eax,[esi-STAKSAFE*16]
  1603.         mov nextmodestack,ax
  1604.         mov ebx,cp_tssesp0ptr
  1605.         push dword ptr [ebx]
  1606.         add eax,realstackbase
  1607.         mov [ebx],eax
  1608.         push cp_savedstakoff
  1609.         mov cp_savedstakoff,esp
  1610.         xor eax,eax
  1611.         push eax
  1612.         push eax
  1613.         mov ax,v86r_ds
  1614.         push eax
  1615.         mov ax,v86r_es
  1616.         push eax
  1617.         mov ax,codeend
  1618.         push eax
  1619.         push esi
  1620.         or edi,20000h
  1621.         and di,0fdffh
  1622.         push edi
  1623.         db 68h                  ; 32bit PUSH code16
  1624.         dd code16               ;
  1625.         push ebp
  1626. cp_int3_m0:                             ; modified under VCPI
  1627. VCPIINT3_M0=(vp_int3_-5)-$              ;
  1628.         iretd
  1629.         db 4 dup(?)             ; buffer for modifiable instruction
  1630. cp_int3_d:
  1631.         mov ax,18h
  1632.         mov gs,ax
  1633.         mov ax,10h
  1634.         mov ds,ax
  1635.         mov es,ax
  1636.         mov fs,ax
  1637.         mov ss,ax
  1638.         mov esp,cp_savedstakoff
  1639.         pop cp_savedstakoff
  1640.         mov ebx,cp_tssesp0ptr
  1641.         pop dword ptr [ebx]
  1642.         mov bx,v86r_flags
  1643. ;-----------------------------------------------------------------------------
  1644. cp_int3_d2:                             ; done with INT32/33 from real or V86
  1645.         add nextmodestack,STAKSAFE*16
  1646.         mov ax,[esp+40]
  1647.         and ax,not 8d5h
  1648.         and bx,8d5h
  1649.         or ax,bx
  1650.         mov [esp+40],ax
  1651.         popad
  1652.         iretd
  1653. ;═════════════════════════════════════════════════════════════════════════════
  1654. cp_rint32:                              ; custom real INT 32h: EDX=off
  1655.         mov gs,cx
  1656.         mov ax,ss
  1657.         mov ds,ax
  1658.         mov es,ax
  1659.         mov fs,ax
  1660.         sub nextmodestack,STAKSAFE*16
  1661.         mov eax,v86r_eax
  1662.         mov ecx,v86r_ecx
  1663.         mov edx,v86r_edx
  1664.         mov ebx,v86r_ebx
  1665.         mov esi,v86r_esi
  1666.         mov edi,v86r_edi
  1667.         mov ebp,v86r_ebp
  1668.         push word ptr [esp+40]
  1669.         popf
  1670.         cld
  1671.         call dword ptr [esp+20]
  1672.         cli
  1673.         mov v86r_eax,eax
  1674.         mov v86r_ecx,ecx
  1675.         mov v86r_edx,edx
  1676.         mov v86r_ebx,ebx
  1677.         mov v86r_esi,esi
  1678.         mov v86r_edi,edi
  1679.         mov v86r_ebp,ebp
  1680.         pushf
  1681.         pop bx
  1682.         jmp cp_int3_d2
  1683. ;═════════════════════════════════════════════════════════════════════════════
  1684. cp_excd:                                ; general protection violation
  1685.         test byte ptr [esp+14],2
  1686.         jnz short cp_excdv86
  1687.         pushad
  1688.         mov al,0dh
  1689.         jmp cp_exc
  1690. ;-----------------------------------------------------------------------------
  1691. cp_excdv86:                             ; violation from V86 mode
  1692.         add esp,4
  1693.         pushad
  1694.         mov cx,18h
  1695.         mov ds,cx
  1696.         movzx ebx,word ptr [esp+36]
  1697.         shl ebx,4
  1698.         add ebx,[esp+32]
  1699.         inc word ptr [esp+32]
  1700.         mov al,[ebx]
  1701.         mov edx,3
  1702.         cmp al,0cch
  1703.         je short cp_v86int
  1704.         mov dl,4
  1705.         cmp al,0ceh
  1706.         je short cp_v86int
  1707.         inc word ptr [esp+32]
  1708.         mov dl,[ebx+1]
  1709.         cmp dl,32h
  1710.         je cp_rint32
  1711.         cmp dl,0ffh
  1712.         je cp_int3_d
  1713. ;-----------------------------------------------------------------------------
  1714. cp_v86int:                              ; need to simulate a real mode int
  1715.         movzx ebx,word ptr [esp+48]
  1716.         shl ebx,4
  1717.         sub word ptr [esp+44],6
  1718.         add ebx,[esp+44]
  1719.         mov ax,[esp+40]
  1720.         mov [ebx+4],ax
  1721.         and ah,0fch
  1722.         mov [esp+41],ah
  1723.         mov ax,[esp+36]
  1724.         mov [ebx+2],ax
  1725.         mov ax,[esp+32]
  1726.         mov [ebx],ax
  1727.         mov eax,[edx*4]
  1728.         mov [esp+32],ax
  1729.         shr eax,16
  1730.         mov [esp+36],ax
  1731.         popad
  1732.         iretd
  1733. ;═════════════════════════════════════════════════════════════════════════════
  1734. ; all exceptions except 0dh. some are terminal, others are redirected.
  1735. cp_exc0:
  1736.         push ax
  1737.         xor al,al
  1738.         jmp cp_irq
  1739. cp_exc1:
  1740.         push ax
  1741.         mov al,1
  1742.         jmp cp_irq
  1743. cp_exc2:
  1744.         push ax
  1745.         mov al,2
  1746.         jmp cp_irq
  1747. cp_exc3:
  1748.         push ax
  1749.         mov al,3
  1750.         jmp cp_irq
  1751. cp_exc4:
  1752.         push ax
  1753.         mov al,4
  1754.         jmp cp_irq
  1755. cp_exc5:
  1756.         push ax
  1757.         mov al,5
  1758.         jmp cp_irq
  1759. cp_exc6:
  1760.         pushad
  1761.         mov al,6
  1762.         jmp short cp_exc
  1763. cp_exc7:
  1764.         push ax
  1765.         mov al,7
  1766.         jmp cp_irq
  1767. cp_exc8:
  1768.         pushad
  1769.         mov al,8
  1770.         jmp short cp_exc
  1771. cp_exc9:
  1772.         pushad
  1773.         mov al,9
  1774.         jmp short cp_exc
  1775. cp_exca:
  1776.         pushad
  1777.         mov al,0ah
  1778.         jmp short cp_exc
  1779. cp_excb:
  1780.         pushad
  1781.         mov al,0bh
  1782.         jmp short cp_exc
  1783. cp_excc:
  1784.         pushad
  1785.         mov al,0ch
  1786.         jmp short cp_exc
  1787. cp_exce:
  1788.         pushad
  1789.         mov al,0dh
  1790.         jmp short cp_exc
  1791. cp_excf:
  1792.         pushad
  1793.         mov al,-1
  1794. ;-----------------------------------------------------------------------------
  1795. cp_exc:                                 ; main exception handler
  1796.     mov ax,10h
  1797.         mov ds,ax
  1798.         mov es,ax
  1799.         mov fs,ax
  1800.         mov gs,_selzero
  1801.     cld
  1802.         jmp _exit
  1803. ;═════════════════════════════════════════════════════════════════════════════
  1804. ; IRQ redirector between modes
  1805. cp_irq0:
  1806.         push ax
  1807.         mov al,8
  1808.         jmp short cp_irq
  1809. cp_irq1:
  1810.         push ax
  1811.         mov al,9
  1812.         jmp short cp_irq
  1813. cp_irq2:
  1814.         push ax
  1815.         mov al,0ah
  1816.         jmp short cp_irq
  1817. cp_irq3:
  1818.         push ax
  1819.         mov al,0bh
  1820.         jmp short cp_irq
  1821. cp_irq4:
  1822.         push ax
  1823.         mov al,0ch
  1824.         jmp short cp_irq
  1825. cp_irq5:
  1826.         push ax
  1827.         mov al,0dh
  1828.         jmp short cp_irq
  1829. cp_irq6:
  1830.         push ax
  1831.         mov al,0eh
  1832.         jmp short cp_irq
  1833. cp_irq7:
  1834.         push ax
  1835.         mov al,0fh
  1836.         jmp short cp_irq
  1837. cp_irq8:
  1838.         push ax
  1839.         mov al,70h
  1840.         jmp short cp_irq
  1841. cp_irq9:
  1842.         push ax
  1843.         mov al,71h
  1844.         jmp short cp_irq
  1845. cp_irqa:
  1846.         push ax
  1847.         mov al,72h
  1848.         jmp short cp_irq
  1849. cp_irqb:
  1850.         push ax
  1851.         mov al,73h
  1852.         jmp short cp_irq
  1853. cp_irqc:
  1854.         push ax
  1855.         mov al,74h
  1856.         jmp short cp_irq
  1857. cp_irqd:
  1858.         push ax
  1859.         mov al,75h
  1860.         jmp short cp_irq
  1861. cp_irqe:
  1862.         push ax
  1863.         mov al,76h
  1864.         jmp short cp_irq
  1865. cp_irqf:
  1866.         push ax
  1867.         mov al,77h
  1868. ;-----------------------------------------------------------------------------
  1869. cp_irq:                                 ; select IRQ type: real->v86 or p->v86
  1870.         mov ss:cp_v86irqnum,al
  1871.         pop ax
  1872.         test byte ptr [esp+10],2
  1873.         jnz short cp_irqv86
  1874.         push ds es fs gs                ; a real mode IRQ in protected mode
  1875.         pushfd
  1876.         push cs
  1877.         push offset cp_irqpd
  1878.         pushad
  1879.         mov ax,ss
  1880.         mov ds,ax
  1881.         mov gs,_selzero
  1882.         movzx eax,cp_v86irqnum
  1883.         mov ecx,gs:[eax*4]
  1884.         mov ebp,offset c_irqreal
  1885.         jmp cp_int3_
  1886. cp_irqpd:
  1887.         pop gs fs es ds
  1888.         iretd
  1889. ;-----------------------------------------------------------------------------
  1890. cp_irqv86:                              ; an IRQ from V86 mode
  1891.         pushad
  1892.         mov ax,18h
  1893.         mov ds,ax
  1894.         movzx edx,ss:cp_v86irqnum
  1895.         jmp cp_v86int
  1896.  
  1897. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1898. ; Custom get IRQ handler offset
  1899. ; In:
  1900. ;   BL - IRQ num (0-0fh)
  1901. ; Out:
  1902. ;   EDX - offset of IRQ handler
  1903. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1904. cp_getirq:
  1905.         push ebx
  1906.         pushf
  1907.         cli
  1908.         movzx ebx,bl
  1909.         mov bl,intslotnum[ebx]
  1910.         lea ebx,[ebx*8]
  1911.         add ebx,cp_idt32ptr
  1912.         mov dx,[ebx+6]
  1913.         shl edx,16
  1914.         mov dx,[ebx]
  1915.         popf
  1916.         pop ebx
  1917.         ret
  1918. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1919. ; Custom set IRQ handler offset
  1920. ; In:
  1921. ;   BL - IRQ num (0-0fh)
  1922. ;   EDX - offset of IRQ handler
  1923. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1924. cp_setirq:
  1925.         push ebx
  1926.         pushf
  1927.         cli
  1928.         movzx ebx,bl
  1929.         mov bl,intslotnum[ebx]
  1930.         lea ebx,[ebx*8]
  1931.         add ebx,cp_idt32ptr
  1932.         mov [ebx],dx
  1933.         shr edx,16
  1934.         mov [ebx+6],dx
  1935.         popf
  1936.         pop ebx
  1937.         ret
  1938.  
  1939. code32  ends
  1940.  
  1941. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  1942. ; End of program (must be at end of program or you will suffer)
  1943. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  1944. codeend segment para stack use32 'stack'
  1945. db STAKLEN*16 dup(?)
  1946. codeend ends
  1947.         end     start16
  1948.  
  1949.